526. 优美的排列
526. 优美的排列
Similar Question
Solution Tips
方案一: 回溯
我们可以使用回溯法解决本题,从左向右依次向目标排列中放入数即可。
具体地,我们定义函数 backtrack(index,n)
, 表示尝试向位置 index 放入数。其中 n 表示排列的长度。在当前函数中,我们首先找到一个符合条件的未被使用过的数,然后递归地执行 backtrack(index+1,n)
,当该函数执行完毕,回溯到当前层,我们再尝试下一个符合条件的未被使用过的数即可。
回溯过程中,我们可以用 vis 数组标记哪些数被使用过,每次我们选中一个数 x,我们就将 vis[x]
标记为 true,回溯完成后,我们再将其置为 false。
特别地,为了优化回溯效率,我们可以预处理每个位置的符合条件的数有哪些,用二维数组 match 保存。当我们尝试向位置 index 放入数时,我们只需要遍历
match[index]
即可。
var countArrangement = function(n) {
const vis = new Array(n + 1).fill(0);
const match = new Array(n + 1).fill(0);
let num = 0;
for (let i = 0; i <= n; i++) {
match[i] = [];
}
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= n; j++) {
if (i % j === 0 || j % i === 0) {
match[i].push(j);
}
}
}
const backtrack = (index, n) => {
if (index === n + 1) {
num++;
return;
}
for (const x of match[index]) {
if (!vis[x]) {
vis[x] = true;
backtrack(index + 1, n);
vis[x] = false;
}
}
}
backtrack(1, n);
return num;
};